package edu.rpi.tw.escience.stargazer.server;

import edu.rpi.tw.escience.stargazer.onto.Star;
import info.aduna.iteration.CloseableIteration;
import org.openrdf.elmo.ElmoManager;
import org.openrdf.elmo.ElmoModule;
import org.openrdf.elmo.Entity;
import org.openrdf.elmo.sesame.SesameManager;
import org.openrdf.elmo.sesame.SesameManagerFactory;
import org.openrdf.model.Statement;
import org.openrdf.model.URI;
import org.openrdf.model.impl.URIImpl;
import org.openrdf.model.vocabulary.RDF;
import org.openrdf.repository.Repository;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;

import javax.xml.namespace.QName;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;

/**
 * Created by IntelliJ IDEA.
 * User: josh
 * Date: Nov 10, 2008
 * Time: 11:00:33 PM
 * To change this template use File | Settings | File Templates.
 */
public class StarGazerContext {
    private Repository repository;
    private ElmoManager elmoManager;
    private QName context;

    public StarGazerContext(final Repository repo) {
        this(repo, null);
    }

    public StarGazerContext(final Repository repo,
                            final QName context) {
        this.repository = repo;
        this.context = context;
        ElmoModule elmoModule = new ElmoModule();
        if (null != context) {
            elmoModule.setContext(context);
        }

        // Record all roles.
        elmoModule.addRole(edu.rpi.tw.escience.stargazer.onto.BrightGiant.class);
        elmoModule.addRole(edu.rpi.tw.escience.stargazer.onto.BrownDwarf.class);
        elmoModule.addRole(edu.rpi.tw.escience.stargazer.onto.CelestialObject.class);
        elmoModule.addRole(edu.rpi.tw.escience.stargazer.onto.Giant.class);
        elmoModule.addRole(edu.rpi.tw.escience.stargazer.onto.Hypergiant.class);
        elmoModule.addRole(edu.rpi.tw.escience.stargazer.onto.MainSequenceStar.class);
        elmoModule.addRole(edu.rpi.tw.escience.stargazer.onto.NormalStar.class);
        elmoModule.addRole(edu.rpi.tw.escience.stargazer.onto.ObservationPoint.class);
        elmoModule.addRole(edu.rpi.tw.escience.stargazer.onto.RedDwarf.class);
        elmoModule.addRole(edu.rpi.tw.escience.stargazer.onto.SpectralType.class);
        elmoModule.addRole(edu.rpi.tw.escience.stargazer.onto.Star.class);
        elmoModule.addRole(edu.rpi.tw.escience.stargazer.onto.Subdwarf.class);
        elmoModule.addRole(edu.rpi.tw.escience.stargazer.onto.Subgiant.class);
        elmoModule.addRole(edu.rpi.tw.escience.stargazer.onto.Supergiant.class);
        elmoModule.addRole(edu.rpi.tw.escience.stargazer.onto.WhiteDwarf.class);

        SesameManagerFactory factory = new SesameManagerFactory(elmoModule, repository);
        SesameManager sm = factory.createElmoManager();
        factory.close();
        elmoManager = sm;
    }

    public void close() {
        elmoManager.close();
    }

    public Repository getRepository() {
        return repository;
    }

    public ElmoManager getElmoManager() {
        return elmoManager;
    }

    public URI getContextURI() {
        if (context == null) {
            return null;
        } else {
            return new URIImpl(context.getNamespaceURI() + context.getLocalPart());
        }
    }

    /*
    private Map<URI, Collection<URI>> getSuperClassHierarchy() throws RepositoryException {
        RepositoryConnection rc = repository.getConnection();
        boolean includeInferred = false;

        try {
             CloseableIteration<? extends Statement, RepositoryException> iter
                    = rc.getStatements(null, RDF.TYPE, null, includeInferred);
            try {
                while (iter.hasNext()) {

                }
            } finally {
                iter.close();
            }

        } finally {
            rc.close();
        }
    }*/

    public Collection<Star> getAllStars() throws RepositoryException {
        Collection<URI> stars = new HashSet<URI>();

        RepositoryConnection rc = repository.getConnection();

        try {
            // We need RDFS inference for this query.
            boolean includeInferred = true;
            CloseableIteration<? extends Statement, RepositoryException> iter
                    = rc.getStatements(null, RDF.TYPE, StarGazer.STAR, includeInferred);

            try {
                while (iter.hasNext()) {
                    stars.add((URI) iter.next().getSubject());
                }
            } finally {
                iter.close();
            }

            Collection<Star> elmoStars = new LinkedList<Star>();
            for (URI u : stars) {
                QName q = new QName(u.toString());

                Star eco = find(Star.class, q);
                if (null == eco) {
                    throw new IllegalArgumentException("eco is null (TODO: this should not be an IllegalArgumentException)");
                } else {
                    elmoStars.add(eco);
                }
            }

            return elmoStars;
        } finally {
            rc.close();
        }
    }

    private <T> T find(final java.lang.Class<T> tClass,
                       final QName q) {
        T eco = null;

        if (null != q) {
            Entity o = getElmoManager().find(q);

            if (tClass.isInstance(o)) {
                eco = (T) o;
            }
        }

        return eco;
    }
}
